[Chapter 7] 7.3 Predefined Macros
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T18:35:12Z

#

| Chapter 7 Macros |

## 7.3 Predefined Macros

The sendmail program internally defines many macros for you. You have already seen `u` (which contains the recipient's username) and `h` (which contains the recipient's hostname) in our delivery agent definitions. They are given values by sendmail instead of being given values with `D` macro definitions in your configuration file. A short list of some of the more common predefined macros is shown in Table 7.1.

Table 7.1: Some Predefined Macros
Macro | Description
--- | ---
n | Identity of the error message sender
v | Version of the currently running sendmail
w | The short hostname
j | The canonical hostname
m | The domain name
k | The UUCP node name
b | Date in RFC1123 format
_ | Identification information
opMode | Current operating mode (beginning with V8.7)

To watch the processing of all the macro definitions, run sendmail once again. This time, add a `-d35.9` debugging switch, which tells sendmail to print each macro as it is defined:

>     % ./sendmail -d35.9 -Cclient.cf -bt < /dev/null

The output that is produced is surprisingly long, considering the small size of the client.cf file:

>     define(* as $*)
>     define(+ as $+)
>     define(- as $-)
>     define(= as $=)
>     define(~ as $~)
>     define(# as $#)
>     define(@ as $@)
>     define(: as $:)
>     define(> as $>)
>     define(? as $?)
>     define(| as $|)
>     define(. as $.)
>     define([ as $[)
>     define(] as $])
>     define(( as $()
>     define() as $))
>     define(& as $&)
>     define(0 as $0)
>     define(1 as $1)
>     define(2 as $2)
>     define(3 as $3)
>     define(4 as $4)
>     define(5 as $5)
>     define(6 as $6)
>     define(7 as $7)
>     define(8 as $8)
>     define(9 as $9)
>     define(n as MAILER-DAEMON)                              note
>     define(v as 8.8.4)                                      note
>     define(w as here.us.edu)                                note
>     define(j as here.us.edu)                                note
>     define(m as us.edu)                                     note
>     define(k as here)                                       note
>     define(b as Fri, 13 Dec 1996 07:11:47 -0700 (PDT))      note
>     define(_ as you@localhost)                              note
>     define(opMode as t)                                     note
>     redefine(w as here)                                     note
>     define(REMOTE as mailhost)                              note

This output will differ from version to version. For example, `l`, `o`, and `e` were macros prior to V8.7 but, beginning with V8.7, are now options. The first 27 lines of this output show sendmail reserving macro names that will be used as operators. (Operators are introduced in the next chapter.) The last 11 definitions are the only ones we are interested in for now. The first 10 of those are internally defined by sendmail for your use. The last definition is caused by sendmail processing the `D{REMOTE}mailhost` line in the client.cf file.

This output demonstrates another concept. Some internal macros are defined before the configuration file is read, so you can change them from inside your client.cf file. To change `w`, for example, you might place the following into your configuration file:

>     Dwmyhost.my.domain

Doing this would then cause the text `myhost.my.domain` to replace the text `here.us.edu` as the value of the macro named `w`.

Note that in the preceding output there were no definitions for the `h` and `u` macros used in the delivery agent definitions. These macros, although internally defined, are not actually given values until mail is sent. You cannot change their values from within your configuration file, because they are not defined until after the configuration file is read.

Finally, note that proper defaults are set only by V8 sendmail. All older versions require you to manually provide defaults for the `e`, `l`, `n`, `o`, and `q` macros in your client.cf file.

### 7.3.1 The hostname

The name of your local machine is composed of two parts. The host part is the machine name and never contains a dot (such as here). The domain part is composed of at least two parts separated from each other by dots (such as us.edu). The fully qualified name of your local machine is made by specifying the host part, then a dot, and finally the domain part (e.g., here.us.edu). The machine's name needs to be fully qualified to uniquely identify it worldwide.

The name of the local machine also needs to be canonical (official and fully qualified). A machine can have multiple names (such as mailhost or printserver), of which only one is official. The official name for the local machine can be found by issuing the hostname(1) command:

>     % hostname
>     here.us.edu

The official name, when fully qualified with a domain, is the canonical name of the machine. Any other names are aliases. [3]

> [3] We are fudging for simplicity. The canonical name is the name associated with the DNS A record. If a machine has multiple network interfaces (and therefore multiple `A` records), it can have multiple canonical names.

To see how sendmail interprets your local hostname, enter the following command, which uses the `-d0.1` debugging switch:

>     % ./sendmail -Cclient.cf -d0.1 -bt </dev/null
>     Version 8.8.4
>      Compiled with: LOG NAMED_BIND NDBM NETINET NETUNIX NIS SCANF XDEBUG

>     ============ SYSTEM IDENTITY (after readcf) ============
>           (short domain name) $w = here
>       (canonical domain name) $j = here.us.edu
>              (subdomain name) $m = us.edu
>                   (node name) $k = here
>     ========================================================

Many things can go wrong here. For example, if you're not on the Internet, you may not have assigned your machine a domain name yet. Or you may be running NIS and have listed only the short name in the hosts.byname map. The important thing to observe in the above output is that sendmail correctly found your short and canonical names:

>           (short domain name) $w = here            short hostname
>       (canonical domain name) $j = here.us.edu     fully qualified canonical name
>              (subdomain name) $m = us.edu          domain

If any are wrong, you need to fix the system problem that led to the error. At the system level, investigate:

- The /etc/hosts file. You may have wrongly listed only short names in it. Prior to V8.7, a fully qualified name had to be listed first. Beginning with V8.7, a fully qualified name can appear anywhere in a line.

- The nis maps. Make sure hostnames are looked up with DNS by specifying the `-b` in /var/yp/Makefile.

- The nsswitch.conf or svc.conf files. Make sure the method used to look up hosts is correctly specified.

If you can't find or don't have permission to fix things at the system level, you can fix them in your client.cf file. Suppose, for example, that the canonical name showed up as the short hostname:

>       (canonical domain name) $j = here            wrong

To fix this, you would need to redefine the `j` macro with a `D` command in the client.cf file:

>     Dj$w.$m               # The local official domain name

This defines the canonical (fully qualified official) name to be the same as the local hostname (`$w`) with a dot and the domain name (`$m`) appended. Rerunning sendmail as above would now display the correct information:

>       (canonical domain name) $j = here.us.edu     correct

In a similar manner you can fix `$w` and `$m` if either of them is wrong. But here we should stress that sendmail goes to great lengths to get this information right.

7.2 Defining Macros |  | 7.4 Things to Try